package com.example.demo.service.impl;

import com.example.demo.entity.SchoolClass;
import com.example.demo.entity.SchoolCourse;
import com.example.demo.entity.SchoolGrade;
import com.example.demo.entity.SchoolStudent;
import com.example.demo.repository.SchooGradeRepository;
import com.example.demo.repository.SchoolClassRepository;
import com.example.demo.repository.SchoolCourseRepository;
import com.example.demo.repository.SchoolStudentRepository;
import com.example.demo.service.SchoolService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class SchoolServiceImpl implements SchoolService {
    private final SchooGradeRepository schooGradeRepository;
    private final SchoolClassRepository schoolClassRepository;
    private final SchoolStudentRepository schoolStudentRepository;
    private final SchoolCourseRepository schoolCourseRepository;

//    public SchoolServiceImpl(SchooGradeRepository schoolGradeRepository, SchoolClassRepository schoolClassRepository, SchoolStudentRepository schoolStudentRepository,SchoolCourseRepository schoolCourseRepository) {
//        this.schooGradeRepository = schoolGradeRepository;
//        this.schoolClassRepository = schoolClassRepository;
//        this.schoolStudentRepository = schoolStudentRepository;
//        this.schoolCourseRepository = schoolCourseRepository;
//    }

    //主从表 查找班级和班级下的学生
    @Override
    public Flux<SchoolClass> findAllSchoolClass() {
        return schoolClassRepository.findAll()
                .flatMap(schoolClass -> schoolStudentRepository.queryAllBySchoolClass(schoolClass.getId())
                        .collectList()
                        .map(schoolStudents -> {
                            schoolClass.setStudents(schoolStudents);
                            return schoolClass;
                        })
                );
    }

    //有条件
    @Override
    public Flux<SchoolClass> findSchoolClassByGrade(Long gradeId) {
        return schoolClassRepository.queryAllBySchoolGrade(gradeId)
                .flatMap(schoolClass -> schoolStudentRepository.queryAllBySchoolClass(schoolClass.getId())
                        .collectList()
                        .map(schoolStudents -> {
                            schoolClass.setStudents(schoolStudents);
                            return schoolClass;
                        })
                );
    }

    //2个并列的
    @Override
    public Flux<SchoolGrade> findAllSchoolGrade() {
        return schooGradeRepository.findAll()
                .flatMap(schoolGrade -> schoolClassRepository.queryAllBySchoolGrade(schoolGrade.getId())
                        .collectList()
                        .map(schoolClass -> {
                            schoolGrade.setSchoolClass(schoolClass);
                            return schoolGrade;
                        })
                )
                .flatMap(schoolGrade->schoolStudentRepository.queryAllBySchoolGrade(schoolGrade.getId())
                        .collectList()
                        .map(schoolStudents -> {
                            schoolGrade.setSchoolStudents(schoolStudents);
                            return schoolGrade;
                        })
                );
    }

    //三级嵌套+二级并联
    @Override
    public Flux<SchoolGrade> findAllSchoolGrade1() {
        return schooGradeRepository.findAll()
                .flatMap(schoolGrade -> schoolClassRepository.queryAllBySchoolGrade(schoolGrade.getId())
                        .flatMap(schoolClass->schoolStudentRepository.queryAllBySchoolClass(schoolClass.getId())
                                    .collectList()
                                    .map(schoolStudents->{
                                        schoolClass.setStudents(schoolStudents);
                                        return schoolClass;
                                    })
                                )
                        .collectList()
                        .map(schoolClass->{
                            schoolGrade.setSchoolClass(schoolClass);
                            return schoolGrade;
                        })
                )
                .flatMap(schoolGrade->schoolStudentRepository.queryAllBySchoolGrade(schoolGrade.getId())
                        .collectList()
                        .map(schoolStudents -> {
                            schoolGrade.setSchoolStudents(schoolStudents);
                            return schoolGrade;
                        })
                );
    }

    //四级嵌套+二级并联
    @Override
    public Flux<SchoolGrade> findAllSchoolGrade2() {
        return schooGradeRepository.findAll()
                .flatMap(schoolGrade -> schoolClassRepository.queryAllBySchoolGrade(schoolGrade.getId())
                        .flatMap(schoolClass->schoolStudentRepository.queryAllBySchoolClass(schoolClass.getId())
                                .flatMap(schoolStudent->schoolCourseRepository.queryAllByStudentId(schoolStudent.getId())
                                        .collectList()
                                        .map(schoolCourse->{
                                            schoolStudent.setSchoolCourses(schoolCourse);
                                            return schoolStudent;
                                        })
                                )
                                .collectList()
                                .map(schoolStudents->{
                                    schoolClass.setStudents(schoolStudents);
                                    return schoolClass;
                                })
                        )
                        .collectList()
                        .map(schoolClass->{
                            schoolGrade.setSchoolClass(schoolClass);
                            return schoolGrade;
                        })
                )
                .flatMap(schoolGrade->schoolStudentRepository.queryAllBySchoolGrade(schoolGrade.getId())
                        .collectList()
                        .map(schoolStudents -> {
                            schoolGrade.setSchoolStudents(schoolStudents);
                            return schoolGrade;
                        })
                );
    }

    //单表保存
    @Override
    public Mono<SchoolGrade> saveSchoolGrade(SchoolGrade schoolGrade){
        return Mono.just(schoolGrade)
                .flatMap(grade->schooGradeRepository.insertOrUpdateGrade(grade))
                .thenReturn(schoolGrade);
    }

    @Override
    public Mono<SchoolClass> saveSchoolClass(SchoolClass schoolClass){
        return Mono.just(schoolClass)
                .flatMap(schoolClass1->schoolClassRepository.insertOrUpdateClass(schoolClass1))
                .thenReturn(schoolClass);
    }

    @Override
    public Mono<SchoolStudent> saveSchoolStudent(SchoolStudent schoolStudent){
        return Mono.just(schoolStudent)
                .flatMap(student->schoolStudentRepository.insertOrUpdateStudent(student))
                .thenReturn(schoolStudent);
    }

    @Override
    public Mono<SchoolCourse> saveSchoolCourse(SchoolCourse schoolCourse){
        return Mono.just(schoolCourse)
                .flatMap(course->schoolCourseRepository.insertOrUpdateCourse(course))
                .thenReturn(schoolCourse);
    }


    //单表多条保存
//    @Override
    public Mono<String> saveSchoolGrades(List<SchoolGrade> schoolGrades){
        return Flux.fromIterable(schoolGrades)
                .flatMap(schoolGrade->schooGradeRepository.insertOrUpdateGrade(schoolGrade))
                .then(Mono.just("ok"));
    }

    //2级保存
    @Override
    public Mono<String> saveClassWithStudents(SchoolClass schoolClass) {
        return Mono.just(schoolClass)
                .flatMap(schoolClass1-> saveSchoolClass(schoolClass1))
                .flatMap(savedClass -> {
                    List<SchoolStudent> schoolStudents = savedClass.getStudents();
                    return Flux.fromIterable(schoolStudents)
                            .flatMap(schoolStudent -> {
                                log.debug(String.valueOf(schoolStudent));
                                return schoolStudentRepository.insertOrUpdateStudent(schoolStudent);})
                            .then(Mono.just("savedClass"));
                });
    }

    //三级保存
    @Override
    public Mono<String> saveClassWithStudentsAndCourses(List<SchoolClass> schoolClasses) {
        return Flux.fromIterable(schoolClasses)
                .flatMap(schoolClass->saveSchoolClass(schoolClass))
                .flatMap(savedClass -> {
                    List<SchoolStudent> schoolStudents = savedClass.getStudents();
                    return Flux.fromIterable(schoolStudents)
                            .flatMap(schoolStudent -> saveSchoolStudent(schoolStudent)
                                    .flatMap(savedStudent->{
                                        List<SchoolCourse> schoolCourses = savedStudent.getSchoolCourses();
                                        return Flux.fromIterable(schoolCourses)
                                                .flatMap(schoolCourse->saveSchoolCourse(schoolCourse))
                                                .then(Mono.just(savedStudent));
                                    }))
                            .then(Mono.just(savedClass));
                })
                .then(Mono.just("OK"));
    }

    //四级保存
    @Override
    public Mono<String> saveSchoolGradeOne(SchoolGrade schoolGrade){
        return Mono.just(schoolGrade)
                .flatMap(grade->schooGradeRepository.save(grade))
                .flatMap(savedGrades -> {
                    List<SchoolClass> schoolClasses = savedGrades.getSchoolClass();
                    return Flux.fromIterable(schoolClasses)
                            .flatMap(schoolClass->schoolClassRepository.save(schoolClass))
                            .flatMap(saveClass->{
                                List<SchoolStudent> schoolStudents = saveClass.getStudents();
                                return Flux.fromIterable(schoolStudents)
                                        .flatMap(schoolStudent -> schoolStudentRepository.save(schoolStudent)
                                                .flatMap(savedStudent->{
                                                    List<SchoolCourse> schoolCourses = savedStudent.getSchoolCourses();
                                                    return Flux.fromIterable(schoolCourses)
                                                            .flatMap(schoolCourse->{
//                                                                schoolCourse.setStudent_id(savedStudent.getId());
                                                                return schoolCourseRepository.save(schoolCourse);})
                                                            .then(Mono.just(savedStudent));
                                                }))
                                        .then(Mono.just(saveClass));
                            })
                            .then(Mono.just(savedGrades));
                })
                .then(Mono.just("OK"));
    }

    //四级保存
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Mono<String> saveSchoolGradeList(List<SchoolGrade> schoolGrades){
        return Flux.fromIterable(schoolGrades)
                .flatMap(schoolGrade->saveSchoolGrade(schoolGrade))
                .flatMap(savedGrade -> {
                    List<SchoolClass> schoolClasses = savedGrade.getSchoolClass();
                    return Flux.fromIterable(schoolClasses)
                            .flatMap(schoolClass->saveSchoolClass(schoolClass))
                            .flatMap(saveClass->{
                                List<SchoolStudent> schoolStudents = saveClass.getStudents();
                                return Flux.fromIterable(schoolStudents)
                                        .flatMap(schoolStudent -> saveSchoolStudent(schoolStudent)
                                                .flatMap(savedStudent->{
                                                    List<SchoolCourse> schoolCourses = savedStudent.getSchoolCourses();
                                                    return Flux.fromIterable(schoolCourses)
                                                            .flatMap(schoolCourse->saveSchoolCourse(schoolCourse))
                                                            .then(Mono.just(savedStudent));
                                                }))
                                        .then(Mono.just(saveClass));
                            })
                            .then(Mono.just(savedGrade));
                })
                .then(Mono.just("Success"));
    }


//    @Override
//    @Transactional(rollbackFor = Throwable.class)
//    public Mono<String> saveSchoolGradeList(List<SchoolGrade> schoolGrades){
//        return Flux.fromIterable(schoolGrades)
//                .flatMap(schoolGrade->schooGradeRepository.save(schoolGrade))
//                .flatMap(savedGrade -> {
//                    List<SchoolClass> schoolClasses = savedGrade.getSchoolClass();
//                    return Flux.fromIterable(schoolClasses)
//                            .flatMap(schoolClass->schoolClassRepository.save(schoolClass))
//                            .flatMap(saveClass->{
//                                List<SchoolStudent> schoolStudents = saveClass.getStudents();
//                                return Flux.fromIterable(schoolStudents)
//                                        .flatMap(schoolStudent -> schoolStudentRepository.save(schoolStudent)
//                                                .flatMap(savedStudent->{
//                                                    List<SchoolCourse> schoolCourses = savedStudent.getSchoolCourses();
//                                                    return Flux.fromIterable(schoolCourses)
//                                                            .flatMap(schoolCourse->schoolCourseRepository.save(schoolCourse))
//                                                            .then(Mono.just(savedStudent));
//                                                }))
//                                        .then(Mono.just(saveClass));
//                            })
//                            .then(Mono.just(savedGrade));
//                })
//                .then(Mono.just("Success"));
//    }


    //主从表 删除班级和班级下的学生
    @Override
    public Mono<Void> deleteSchoolClassAndStudentsById(Long Id) {
        return schoolStudentRepository.deleteByClassId(Id)
                .then(schoolClassRepository.deleteById(Id))
                .then();
    }


    //三级嵌套
    @Override
    public Mono<String> deleteSchoolClassAndStudentsAndCoursesById(Long Id) {
        return  schoolCourseRepository.deleteAllByClassId(Id)
                .then(schoolStudentRepository.deleteByClassId(Id))
                .then(schoolClassRepository.deleteById(Id))
                .thenReturn("删除成功！");
    }

}
